#include <windows.h>
#include <stdio.h>
#include "Param.h"

TParam paramList[] = 
{
	param_normal("pak", "pak_file", "The file containing the definitions (see below for example)", ptype_string),
	param_normal("def", "header_file", "Generated file that will contain the index positions", ptype_string),
	param_switch("zip", "Compress the files uzing zip (deflate) algorithm"),
	param_switch("v", "Verbose mode, outputs info about files"),

	param_simple("output_file", "The output file", true)
};

enum
{
	PARAM_PAK = 0,
	PARAM_DEFS,
	PARAM_ZIP,
	PARAM_VERBOSE,
	PARAM_OUTPUT
}EParams;

typedef struct __node
{
	__node *next;
	char *desc;
	char *file;
	long size;
	long pos;
}TFilePair;

TFilePair *files;

void addFile(TFilePair *pair, FILE *fpak)
{
	pair->size = 0;
	FILE *f = fopen(pair->file, "rb");
	if (!f)
	{
		printf("Skipping %s\n",pair->file);	
		return;
	}

	fseek(f, 0, SEEK_END);
	long len = ftell(f);
	fseek(f,0,SEEK_SET);
	char *data = new char[len];
	fread(data, len, 1, f);
	fwrite(data, len, 1, fpak);
	delete[] data;

	if (paramList[PARAM_VERBOSE].assigned)
		printf("Adding %02d%% %s\n",100,pair->file);
	pair->size = len;
}

int main(int argc, char **argv)
{
	//parse command line
	if (!parseCommand(argc, argv, paramList, sizeof(paramList) / sizeof(TParam),"The pak file should be in format: definition filename\nExample:\n\nFILE_STRINGS\tstrings.dat\nFILE_PICS\tpics.dat\n\nwill create a pak with two files\n\n(c)2008 Claudiu-Florin FILIMON"))
		return -1;

	//create list
	files = new TFilePair;
	files->next = NULL;
	files->desc = NULL;
	files->file = NULL;
	TFilePair *last = files;

	FILE *f = fopen(paramList[PARAM_PAK].strValue, "rt");
	if (!f)
	{
		printf("Can't open pak file %s\n",paramList[PARAM_PAK].strValue);
		return -1;
	}

	char line[1024];
	int maxLen = 0;

	//parse command file
	while (fgets(line, 1024, f))
	{
		char desc[1024];
		char file[1024];

		//get desc and file
		int p = 0, dLen=0, fLen=0;
		while ((line[p] == ' ') || (line[p] == '\t'))
			p++;
		while (line[p] && (line[p] != ' ') && (line[p] != '\t') && (line[p] != '\n'))
			desc[dLen++] = line[p++];
		desc[dLen] = 0;

		while ((line[p] == ' ') || (line[p] == '\t'))
			p++;
		while (line[p] && (line[p] != ' ') && (line[p] != '\t') && (line[p] != '\n'))
			file[fLen++] = line[p++];
		file[fLen] = 0;

		if (dLen > maxLen)
			maxLen = dLen;
			
		if ((dLen>0)&&(fLen>0))
		{
			//create a new entry
			TFilePair *fp = new TFilePair;
			last->next = fp;
			last = fp;
			fp->next = NULL;

			fp->desc = new char[dLen+1];
			strcpy(fp->desc, desc);

			fp->file = new char[fLen+1];
			strcpy(fp->file, file);

			fp->size = 0;
			fp->pos = 0;
		}
	}

	fclose(f);

	//write h file
	f = fopen(paramList[PARAM_DEFS].strValue, "wt");
	if (!f)
	{
		printf("Can't open pak file %s\n",paramList[PARAM_DEFS].strValue);
		return -1;
	}

	char hFile[1024];
	strcpy(hFile, paramList[PARAM_DEFS].strValue);

	for (int i=0;hFile[i];i++)
	{
		if ((hFile[i]=='.')||(hFile[i]=='/')||(hFile[i]=='\\'))
			hFile[i] = '_';
		if ((hFile[i]>='a')&&(hFile[i]<='z'))
			hFile[i] -= 'a' - 'A';
	}
		
	fprintf(f,"#ifndef _%s_\n#define _%s_\n\n",hFile,hFile);
	fprintf(f,"//\n// File autogenerated by makePak.exe, do not modify\n//\n\n");

	//loop trough all defs, write them to h
	short count = 0;
	last = files->next;
	while (last)
	{
		char s[1024];
		int len = strlen(last->desc);

		int i = 0;
		while (len+i<maxLen)
			s[i++]=' ';
		s[i] = 0;

		fprintf(f,"#define %s%s   %d\n",last->desc, s, count);

		count++;
		last = last->next;
	}

	fprintf(f,"\n#endif //_%s_\n",hFile);
	fclose(f);

	//open file
	f = fopen(paramList[PARAM_OUTPUT].strValue, "wb");
	if (!f)
	{
		printf("Can't open pak file %s\n",paramList[PARAM_OUTPUT].strValue);
		return -1;
	}

	fwrite("PK", 2, 1, f);	//signature
	short flags = 0;
	fwrite(&flags, 2, 1, f);	//flags

	fwrite(&count, 2, 1, f);	//how many files


	for (int i=0;i<count;i++)
	{
		long t = 0;
		fwrite(&t,4,1,f);	//file pos
		fwrite(&t,4,1,f);	//file size
	}

	long pos = 0;
	last = files->next;
	while (last)
	{
		addFile(last, f);	//add the files
		last->pos = pos;
		pos += last->size;

		last = last->next;
	}

	//write header
	fseek(f, 6, SEEK_SET);
	last = files->next;
	while (last)
	{
		fwrite(&(last->pos), 4, 1, f);
		fwrite(&(last->size), 4, 1, f);
		last = last->next;
	}


	fclose(f);


	//delete list
	while (files)
	{
		last = files->next;
		if (files->file)
			delete[] files->file;
		if (files->desc)
			delete[] files->desc;
		delete files;
		files = last;
	}

	return 0;
}